#include <iostream>
#include <fstream>
#include <iomanip>
#include <sys/types.h>
#include <string.h>
#include <getopt.h> 

#include "ConfigReader.h"

using namespace std;

ConfigReader::ConfigReader()
{
  fargc=0;
  cfg_filename=0;
}

/// reads in options from a configfile
/// whitespace is ignored
/// everything between '#' and '\n' is ignored
/// 
void ConfigReader::readConfigFile() throw(IOError)
{
    std::ifstream in(cfg_filename);

    if(!in)
      throw IOError((string("ConfigReader::readConfigFile():\n"
			    "  error by opening file \"")
		            + cfg_filename +"\"").c_str()
		    ,0);

    fargv[0] = new char[strlen(cfg_filename)+1];
    fargv[1] = 0;
    strcpy(fargv[0],cfg_filename);
    fargc=1;

    char c;
    int lineno=0;
    int buflen=1024;
    char buf[buflen];
    while(in.get(c)) {
      switch(c) {
      case ' ':    //whitespace
      case '\t':   //whitespace
	break;

      case '\n':   //whitespace
	lineno++;
	break;

      case '#':
	//std::cout << "comment in line: " << lineno << std::endl;

	while(in.get(c))
	  if(c=='\n') {
	    lineno++; break;
	  }
	break;

      default:
	int i=0; buf[i]=c; i++;
	while(in.get(c)) {
	  if(i>=buflen)
	    throw IOError("ConfigReader::readConfigFile():\n"
			  "  option to long",0);

	  if(c=='\n' || c==' ' || c=='\t') {
	    if(c=='\n') lineno++;
	    buf[i]=0;

	    if(fargc>=farg_size)
	      throw IOError("ConfigReader::readConfigFile():\n"
			  "  to many arguments",0);

	    fargv[fargc] = new char[strlen(buf)+1];
	    strcpy(fargv[fargc],buf);
	    fargv[fargc+1] = 0;
	    fargc++; break;
	  }
	  buf[i]=c; i++;
	}
	// without the following lines, the config file would have to end
	// with a newline or white space
	if(in.eof() && i>0) {
	    buf[i]=0;

	    if(fargc>=farg_size)
	      throw IOError("ConfigReader::readConfigFile():\n"
			  "  to many arguments",0);

	    fargv[fargc] = new char[strlen(buf)+1];
	    strcpy(fargv[fargc],buf);
	    fargv[fargc+1] = 0;
	    fargc++; break;
	}
      }
    }

    in.close();
}

void ConfigReader::getConfigFileName(int *argc, char *argv[])
  throw(IOError)
{
  for(int i=0; i<(*argc); i++)
    if(!strcmp("--config-file",argv[i]) || !strcmp("-f",argv[i])) {

      if( (i==(*argc)-1) || (argv[i+1][0]=='-') )
	throw IOError( (string("ConfigReader::getConfigFileName():\n"
	                       "  argument expected for option ")
			+argv[i]).c_str(),i);      
      
      cfg_filename = new char[strlen(argv[i+1])+1];
      strcpy(cfg_filename,argv[i+1]);

      for(int j=i; j<(*argc)-2; j++) {
	argv[j] = argv[j+2];
      }
      (*argc) -= 2;

      break;
    }
}
